package handler

import (
	"context"
	"go-likaladi-shop/common/base_global"
	"go-likaladi-shop/common/base_util"
	"google.golang.org/grpc/codes"
	"google.golang.org/protobuf/types/known/emptypb"
	"lw-shop/goods_service/model"
	"lw-shop/goods_service/proto"
)

func (s *GoodsService) CategoryBrandList(ctx context.Context, req *proto.CategoryBrandFilterRequest) (*proto.CategoryBrandListResponse, error) {
	var categoryBrands []model.GoodsCategoryBrand
	categoryBrandListResponse := proto.CategoryBrandListResponse{}
	var total int64
	base_global.DB.Model(&model.GoodsCategoryBrand{}).Count(&total)
	categoryBrandListResponse.Total = int32(total)

	//select * from xx where
	result := base_global.DB.Scopes(base_util.Paginate(int(req.Pages), int(req.PagePerNums))).Find(&categoryBrands)
	if result.Error != nil {
		return nil, base_util.GrpcError(result.Error)
	}

	var categoryResponses []*proto.CategoryBrandResponse
	for _, categoryBrand := range categoryBrands {
		categoryResponses = append(categoryResponses, &proto.CategoryBrandResponse{
			Id:            categoryBrand.ID,
			CategoryId:    categoryBrand.CategoryID,
			BrandsId:      categoryBrand.BrandsID,
			CreatedTime:   uint64(categoryBrand.CreatedTime.Unix()),
			CreateTimeStr: categoryBrand.CreatedTime.Format("2006-01-02 15:04:05"),
		})
	}
	categoryBrandListResponse.Data = categoryResponses

	return &categoryBrandListResponse, nil
}

// GetCategoryBrandList 获取某个分类下绑定的品牌列表
func (s *GoodsService) GetCategoryBrandList(ctx context.Context, req *proto.CategoryBrandRequest) (*proto.BrandListResponse, error) {
	// 声明用于存储查询结果的切片
	var categoryBrands []model.GoodsCategoryBrand

	// 根据分类ID查询中间表 goodscategorybrand，获取所有绑定的品牌记录
	if result := base_global.DB.Where(&model.GoodsCategoryBrand{CategoryID: req.CategoryId}).Find(&categoryBrands); result.Error != nil {
		// 如果查询出错，返回错误
		return nil, result.Error
	}

	// 提取所有品牌ID，准备批量查询品牌详细信息
	var brandIds []int32
	for _, categoryBrand := range categoryBrands {
		brandIds = append(brandIds, categoryBrand.BrandsID)
	}

	// 根据品牌ID列表查询品牌详情
	brands, err := QueryBrandsByIds(brandIds)
	if err != nil {
		// 如果查询出错，返回错误
		return nil, err
	}

	// 返回品牌列表响应对象
	return &proto.BrandListResponse{
		Data: brands, // 查询结果作为响应数据返回
	}, nil
}

type CategoryBrandDetail struct {
	CategoryID   int32
	CategoryName string
	BrandID      int32
	BrandName    string
}

// GetCategoryBrandList2 获取指定分类下的品牌列表（包含分类信息与品牌列表）
// 参数：
//   - ctx: gRPC 上下文
//   - req: 请求结构体，包含 CategoryId 分类 ID
//
// 返回：
//   - *proto.CategoryBrandsResponse：包含分类 ID、分类名和品牌列表
//   - error：错误信息（如果有）
func (s *GoodsService) GetCategoryBrandList2(ctx context.Context, req *proto.CategoryBrandRequest) (*proto.CategoryBrandsResponse, error) {
	var results []CategoryBrandDetail // 用于接收 SQL 查询的结果，每行包含分类和品牌信息

	// 构造 SQL 查询：
	// SELECT t1.category_id, t2.name as category_name, t3.id as brand_id, t3.name as brand_name
	// FROM goodscategorybrand t1
	// LEFT JOIN category t2 ON t1.category_id = t2.id
	// LEFT JOIN brands t3 ON t1.brands_id = t3.id
	db := base_global.DB.
		Select("t1.category_id, t2.name as category_name, t3.id as brand_id, t3.name as brand_name").
		Table("goodscategorybrand t1").
		Joins("LEFT JOIN category t2 ON t1.category_id = t2.id").
		Joins("LEFT JOIN brands t3 ON t1.brands_id = t3.id")

	// 添加查询条件：按分类 ID 过滤
	db.Where("t1.category_id = ?", req.CategoryId)

	// 执行查询，将结果映射到 results 切片中
	if err := db.Scan(&results).Error; err != nil {
		// 查询出错，转换为 gRPC 错误返回
		return nil, base_util.GrpcError(err)
	}

	// 定义一个 Map 用于将查询结果按分类 ID 分组（虽然这里只查一个分类，依然保持可扩展性）
	categoryBrandMap := make(map[int32]*proto.CategoryBrandsResponse)

	// 遍历每一行结果，构造分类品牌映射
	for _, r := range results {
		// 检查当前分类是否已存在于 Map 中
		cb, exists := categoryBrandMap[r.CategoryID]
		if !exists {
			// 如果不存在，则初始化一个新的 CategoryBrandsResponse 结构
			cb = &proto.CategoryBrandsResponse{
				CategoryId:   r.CategoryID,
				CategoryName: r.CategoryName,
				Data:         []*proto.BrandInfoResponse{},
			}
		}
		// 向该分类下添加品牌信息
		cb.Data = append(cb.Data, &proto.BrandInfoResponse{
			Id:   r.BrandID,
			Name: r.BrandName,
		})
		// 更新 Map 中的值
		categoryBrandMap[r.CategoryID] = cb
	}

	// 从 Map 中取出当前分类的聚合结果返回（req.CategoryId 是唯一值）
	obj := categoryBrandMap[req.CategoryId]

	return obj, nil
}

func (s *GoodsService) GetCategoryBrandList3(ctx context.Context, req *proto.CategoryBrandRequest) (*proto.CategoryBrandsResponse, error) {
	var results []CategoryBrandDetail // 用于接收 SQL 查询的结果，每行包含分类和品牌信息

	// 构造 SQL 查询：
	// SELECT t1.category_id, t2.name as category_name, t3.id as brand_id, t3.name as brand_name
	// FROM goodscategorybrand t1
	// LEFT JOIN category t2 ON t1.category_id = t2.id
	// LEFT JOIN brands t3 ON t1.brands_id = t3.id
	db := base_global.DB.
		Select("t1.category_id, t2.name as category_name, t3.id as brand_id, t3.name as brand_name").
		Table("goodscategorybrand t1").
		Joins("LEFT JOIN category t2 ON t1.category_id = t2.id").
		Joins("LEFT JOIN brands t3 ON t1.brands_id = t3.id")

	// 添加查询条件：按分类 ID 过滤
	db.Where("t1.category_id = ?", req.CategoryId)

	// 执行查询，将结果映射到 results 切片中
	if err := db.Scan(&results).Error; err != nil {
		// 查询出错，转换为 gRPC 错误返回
		return nil, base_util.GrpcError(err)
	}

	categoryBrandMap := base_util.SliceToMultiMap(results, func(t CategoryBrandDetail) int32 {
		return t.CategoryID
	})

	categoryBrandDetails := categoryBrandMap[req.CategoryId]

	if categoryBrandDetails != nil && len(categoryBrandDetails) > 0 {
		obj := categoryBrandDetails[0]

		var dataList []*proto.BrandInfoResponse
		for _, data := range categoryBrandDetails {
			dataList = append(dataList, &proto.BrandInfoResponse{
				Id:   data.BrandID,
				Name: data.BrandName,
			})
		}
		return &proto.CategoryBrandsResponse{
			CategoryId:   obj.CategoryID,
			CategoryName: obj.CategoryName,
			Data:         dataList,
		}, nil
	}

	return nil, base_util.LogicError("找不到匹配的记录")
}

func (s *GoodsService) CreateCategoryBrand(ctx context.Context, req *proto.CategoryBrandRequest) (*proto.CategoryBrandResponse, error) {
	var category model.Category
	if result := base_global.DB.First(&category, req.CategoryId); result.RowsAffected == 0 {
		return nil, base_util.LogicError("商品分类不存在")
	}
	var brand model.Brands
	if result := base_global.DB.First(&brand, req.BrandId); result.RowsAffected == 0 {
		return nil, base_util.LogicError("品牌不存在")
	}
	categoryBrand := model.GoodsCategoryBrand{
		CategoryID: req.CategoryId,
		BrandsID:   req.BrandId,
	}
	base_global.DB.Save(&categoryBrand)
	return &proto.CategoryBrandResponse{Id: categoryBrand.ID}, nil
}

func (s *GoodsService) DeleteCategoryBrand(ctx context.Context, req *proto.CategoryBrandRequest) (*emptypb.Empty, error) {
	if result := base_global.DB.Delete(&model.GoodsCategoryBrand{}, req.Id); result.RowsAffected == 0 {
		return nil, base_util.GrpcCodeErrorMsg(codes.NotFound, "品牌分类不存在")
	}
	return &emptypb.Empty{}, nil
}

// UpdateCategoryBrand 更新商品的品牌分类关联关系
// 参数：
//   - ctx: gRPC 上下文
//   - req: 请求结构体，包含要更新的关联 ID、新的分类 ID、新的品牌 ID
//
// 返回：
//   - *emptypb.Empty：空返回值表示更新成功
//   - error：错误信息（如品牌分类、分类、品牌不存在）
func (s *GoodsService) UpdateCategoryBrand(ctx context.Context, req *proto.CategoryBrandRequest) (*emptypb.Empty, error) {
	var categoryBrand model.GoodsCategoryBrand

	// 1. 查询当前要更新的品牌分类关系是否存在
	if result := base_global.DB.First(&categoryBrand, req.Id); result.RowsAffected == 0 {
		// 如果不存在，返回逻辑错误提示（可替代 gRPC 的 codes.InvalidArgument）
		return nil, base_util.LogicError("品牌分类不存在")
	}

	// 2. 验证请求中的分类 ID 是否存在于 category 表中
	var category model.Category
	if result := base_global.DB.First(&category, req.CategoryId); result.RowsAffected == 0 {
		return nil, base_util.LogicError("商品分类不存在")
	}

	// 3. 验证请求中的品牌 ID 是否存在于 brands 表中
	var brand model.Brands
	if result := base_global.DB.First(&brand, req.BrandId); result.RowsAffected == 0 {
		return nil, base_util.LogicError("品牌不存在")
	}

	// 4. 所有校验通过，进行更新字段赋值
	categoryBrand.CategoryID = req.CategoryId // 更新分类 ID
	categoryBrand.BrandsID = req.BrandId      // 更新品牌 ID

	// 5. 执行保存操作（保存更新后的品牌分类关联记录）
	base_global.DB.Save(&categoryBrand)

	// 6. 返回空响应，表示更新成功
	return &emptypb.Empty{}, nil
}
